package cn.im.controller;

import cn.im.pojo.User;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.*;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * RestTemplate Demo
 */
public class RestTemplateController {

    private  static final Logger log = LoggerFactory.getLogger(RestTemplateController.class);

    /**
     * get请求 -- getForObject  直接将HTTP转成POJO
     * public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables){}
     * public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
     * public <T> T getForObject(URI url, Class<T> responseType)
     */
    @Test
    public void getForObjectTest(){
        RestTemplate restTemplate = new RestTemplate();
        //返回报文：{"id":"001","userName":"kevin","password":"123","age":17}
        User user = restTemplate.getForObject("http://localhost:8081/api/user/get/001", User.class);
        log.info("不带参数的get请求返回：{}",user.toString());

        user = restTemplate.getForObject("http://localhost:8081/api/user/get/{1}", User.class,"002");
        log.info("占位符链接带参的get请求返回：{}",user==null?"null":user.toString());

        Map<String, String> params = new HashMap<String, String>();
        params.put("id", "003");
        user = restTemplate.getForObject("http://localhost:8081/api/user/get/{id}", User.class,params);
        log.info("map链接带参的get请求返回：{}",user==null?"null":user.toString());

        String result = restTemplate.getForObject("http://localhost:8081/api/user/get/001", String.class);
        log.info("不做报文转换，直接输出返回报文：{}",result);
    }


    /**
     * get请求 -- getForEntity  返回ResponseEntity对象，手动引入json工具转换
     * public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables){}
     * public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables){}
     * public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType){}
     */
    @Test
    public void getForEntityTest(){
        RestTemplate restTemplate = new RestTemplate();
        //ResponseEntity包含了HttpStatus和BodyBuilder
        ResponseEntity<User> entity = restTemplate.getForEntity("http://localhost:8081/api/user/get/001", User.class);

        HttpStatus statusCode = entity.getStatusCode();
        log.info("statusCode.is2xxSuccessful()：{}",statusCode.is2xxSuccessful());
        User body = entity.getBody();
        log.info("entity.getBody().toString():{}",body.toString());
        log.info("entity.getStatusCodeValue():{}",entity.getStatusCodeValue());
        log.info("entity.getStatusCode().toString():{}",entity.getStatusCode().toString());
        log.info("entity.getHeaders().get(\"Content-Type\").toString():{}",entity.getHeaders().get("Content-Type").toString());
    }



    /**
     * post请求
     * postForObject、postForEntity  基本一致，主要是返回类型不同
     * postForLocation：返回uri对象，比如注册成功跳转到登录页面
     */
    @Test
    public void postDataTest(){
        //请求报文格式： {"id":"100","userName":"Robin","password":"456","age":21}
        RestTemplate restTemplate = new RestTemplate();
        String url ="http://localhost:8081/api/user/add";

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        MultiValueMap<Object, Object> map = new LinkedMultiValueMap<>();
        map.add("id","200");
        HttpEntity<MultiValueMap> request = new HttpEntity<>(map,httpHeaders);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, request, String.class);
        log.info("以KV格式发送post请求，返回报文：{}",responseEntity.getBody());

        User user = new User("204","bult","xxxx",34);
        String result = restTemplate.postForObject(url, user, String.class);
        log.info("以json格式发送post请求，返回报文：{}",result);
    }

    /**
     * post请求
     * postForObject、postForEntity  基本一致，主要是返回类型不同
     * postForLocation：返回uri对象，比如注册成功跳转到登录页面
     *
     * @RequestMapping("/register")
     * public String register(User user) throws UnsupportedEncodingException {
     *     return "redirect:/loginPage?username=" + URLEncoder.encode(user.getUsername(),"UTF-8") + "&address=" + URLEncoder.encode(user.getAddress(),"UTF-8");
     * }
     */
    @Test
    public void postForLocationTest(){
        String url ="http://ip:port/xxx/register";

        //通过RestTemplateBuilder创建RestTemplate
        RestTemplateBuilder builder = new RestTemplateBuilder();
        RestTemplate restTemplate = builder.setConnectTimeout(Duration.ofMillis(3000)).setReadTimeout(Duration.ofMillis(5000)).build();

        MultiValueMap map = new LinkedMultiValueMap();
        map.add("username", "牧码小子");
        map.add("address", "深圳");
        URI uri = restTemplate.postForLocation(url, map);
        log.info("以kv格式发送post请求，返回链接：{}",uri);
    }

    /**
     * exchange -- get、post通用
     */
    @Test
    public void exchangeTest(){
        String uri = "http://localhost:8081/api/user/get/402";
        String api = "http://localhost:8081/api/user/add";

        //设置超时时间
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(1000);// 设置超时
        requestFactory.setReadTimeout(1000);
        RestTemplate restTemplate = new RestTemplate(requestFactory);


        HttpHeaders header = new HttpHeaders();
        header.setContentType(MediaType.APPLICATION_JSON);
        String reqJsonStr = "{\"id\":\"402\",\"userName\":\"kevin\",\"password\":\"123\",\"age\":17}";
        HttpEntity<String> request = new HttpEntity<>(reqJsonStr, header);
        ResponseEntity<User> resp = restTemplate.exchange(api, HttpMethod.POST, request, User.class);
        log.info("exchange形式发送post请求，返回报文：{}",resp.getBody());


        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
        ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
        log.info("exchange形式发送get请求，返回报文：{}",result);
    }
}
